package morrior

import (
	"fmt"
	"iot-base/common/fsm"
	"net"
	"strings"
	"sync"

	"github.com/CreditTone/aslist"
)

var fsmBody string

//var edgeFSM string

func init() {
	fsmBody = `[{"name":"begin","transitions":[{"from":"","to":"wait"}],"actionNames":["prepare"]},
	{"name":"prepareOK","transitions":[{"from":"wait","to":"ready"}]},
	{"name":"mirror","transitions":[{"from":"wait","to":"wait"}],"actionNames":["mirror"]},
	{"name":"close","transitions":[{"from":"*","to":"END"}],"actionNames":["free"]},
	{"name":"error","transitions":[{"from":"*","to":"END"}],"actionNames":["free"]}]`
	var ofsm fsm.FSM
	ofsm.SName = "fsmConnection"
	ofsm.UID = "fsmConnection"

	ofsm.Body = []byte(fsmBody)
	fsm.RegisterFSM(&ofsm)

}
func runConnection(pConn *Connection, pInstace *fsm.FSMInstance) {
	pConn.Run(true)
	pInstace.NotifyEvent("timeout")

}

//GetAddrList 获取地址
func GetAddrList(pfsm *fsm.FSMInstance) *aslist.AsList {
	pList, _ := pfsm.GetContext().Get("addrList")
	if pList != nil {
		pResult, _ := pList.(*aslist.AsList)
		return pResult
	}
	return nil
}

//AddAddr 增加地址
func AddAddr(pfsm *fsm.FSMInstance, addr string) {
	pList := GetAddrList(pfsm)
	if pList != nil {
		pList.Push(addr)
	}
}

//RemoveAddr 删除地址
func RemoveAddr(pfsm *fsm.FSMInstance, addr string) {
	pList := GetAddrList(pfsm)
	if pList != nil {
		pList.ClearTargets(func(index int, item interface{}) bool {
			taddr := item.(string)
			return taddr == addr
		})
	}
}

//begin 建立fsmConnection，对于client 一个t1对应一个fsmConnection 一个fsmConnection对应多个模拟链路
func begin(pwg *sync.WaitGroup, pConnection *Connection) *fsm.FSMInstance {
	//建立状态机
	fmt.Println("begin fsm fsmConnection")
	pInstance := fsm.CreateFSMInstance("fsmConnection")
	if pInstance != nil {

		pInstance.GetContext().Set("wg", pwg)
		pInstance.GetContext().Set("tc", pConnection)
		pList := aslist.NewAsList()
		pList.GanerateUniqueId = func(i interface{}) string {
			bi := i.(string)
			return bi
		}
		pInstance.GetContext().Set("addrList", pList)

		fsm.RegisterActionAsFun("fsmConnection", "prepare", prepare)
		fsm.RegisterActionAsFun("fsmConnection", "free", free)
		fsm.RegisterAction("fsmConnection", &MorriorInfo{})
		fmt.Println("begin fsm fsmConnection and notify event begin")
		pInstance.NotifyEvent("begin")
		pConnection.pfsm = pInstance
		go pInstance.RunLoop()
		go runConnection(pConnection, pInstance)
		fmt.Println("begin fsm fsmConnection succ")
	} else {
		fmt.Println("begin fsm fsmConnection failed")
	}
	return pInstance
}

func closeConection(cmdType byte, fakeConnection interface{}) {
	if fakeConnection != nil {
		pConn, _ := fakeConnection.(*net.TCPConn)
		if pConn != nil {
			fmt.Println("-------close------connection-----", pConn.LocalAddr().String())
			if cmdType == ERROR_ON_CONNECTION_SEND {
				pConn.CloseRead()
			} else if cmdType == ERROR_ON_CONNECTION_RECV {
				pConn.CloseWrite()
			} else if cmdType == ERROR_ON_CONNECTION {
				pConn.Close()
			}

		}

	}

}

func free(pFSM *fsm.FSMInstance) error {
	pConnection, _ := pFSM.GetContext().Get("tc")
	if pConnection != nil {
		pConn, _ := pConnection.(*Connection)
		if pConn != nil {
			pConn.Close()
		}
		//pConnection.Close()
	}
	pSvr, _ := pFSM.GetContext().Get("server")
	if pSvr != nil {
		pSvrConnection, _ := pSvr.(net.Conn)
		if pSvrConnection != nil {
			pSvrConnection.Close()
		}
	}
	return nil
}

func prepare(pFSM *fsm.FSMInstance) error {

	role, _ := pFSM.GetContext().GetString("role")
	fmt.Println("prepare runs-----------", role)
	if role == "client" {
		go clientPrepare(pFSM)
	} else {
		go edgePrepare(pFSM)
	}
	return nil

}

func GetMirrorID(netType, targetIP string, port int) string {
	return fmt.Sprintf("%s-%s:%d", netType, targetIP, port)
}

func parseMirrorID(id string) (string, string) {

	parts := strings.Split(id, "-")
	if len(parts) >= 2 {
		return parts[0], parts[1]
	}
	return "", ""
}
